{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "c6e9d322",
   "metadata": {
    "colab_type": "text",
    "id": "view-in-github"
   },
   "source": [
    "<a href=\"https://colab.research.google.com/github/peremartra/Large-Language-Model-Notebooks-Course/blob/main/1-Introduction%20to%20LLMs%20with%20OpenAI/1_1-First_Chatbot_OpenAI_Gradio.ipynb\" target=\"_parent\"><img src=\"https://colab.research.google.com/assets/colab-badge.svg\" alt=\"Open In Colab\"/></a>"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "zwzWskLgXgj5",
   "metadata": {
    "id": "zwzWskLgXgj5"
   },
   "source": [
    "<div>\n",
    "<h1>Large Language Models Projects</h1>\n",
    "    <h3>Apply and Implement Strategies for Large Language Models</h3>\n",
    "    <h2>1.1-Create your first Chatbot With OpenAI and GRADIO</h2>\n",
    "</div>\n",
    "\n",
    "by [Pere Martra](https://www.linkedin.com/in/pere-martra/)\n",
    "___________\n",
    "\n",
    "Models: gpt-3.5-turbo / gpt-4o-mini\n",
    "\n",
    "Colab Environment: CPU\n",
    "\n",
    "Keys:\n",
    "* OpenAI roles.\n",
    "* Memory in conversations.\n",
    "* Gradio\n",
    "\n",
    "Related article: [Create a simple Chatbot with OpenAI and Gradio.](https://medium.com/ai-in-plain-english/create-a-simple-chatbot-with-openai-and-gradio-202684d18f35?sk=e449515ec7a803ae828418011bbaca52)\n",
    "___________________________\n",
    "\n",
    "This is the unofficial repository for the book:\n",
    "        <a href=\"https://amzn.to/4eanT1g\"> <b>Large Language Models:</b> Apply and Implement Strategies for Large Language Models</a> (Apress).\n",
    "        The book is based on the content of this repository, but the notebooks are being updated, and I am incorporating new examples and chapters.\n",
    "        If you are looking for the official repository for the book, with the original notebooks, you should visit the\n",
    "        <a href=\"https://github.com/Apress/Large-Language-Models-Projects\">Apress repository</a>, where you can find all the notebooks in their original format as they appear in the book."
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c23b4dd1",
   "metadata": {
    "id": "c23b4dd1"
   },
   "source": [
    "# Vertical Chat Gradio\n",
    "This is just a simple sample to start understanding how the OpenAI API works, and how to create Prompts. It Is really far from beign a complete solution, but we are going to introduce some interesting points:\n",
    "\n",
    "* The roles in a conversation.\n",
    "* How is the conversations’ memory preserved?\n",
    "* How Gradio works.\n",
    "\n",
    "It is based in the first example of the course that use Panel instead of Gradio.\n",
    "https://github.com/peremartra/Large-Language-Model-Notebooks-Course/blob/main/1-Introduction%20to%20LLMs%20with%20OpenAI/1_1-First_Chatbot_OpenAI.ipynb\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a1d00720",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "a1d00720",
    "outputId": "0fe8fddf-c833-4865-9452-7e4d4e503a27"
   },
   "outputs": [],
   "source": [
    "#First install the necesary libraries\n",
    "!pip install -q openai==1.1.1\n",
    "!pip install -q gradio==4.40.0"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "a03f026a",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/"
    },
    "id": "a03f026a",
    "outputId": "31927aa7-5f7e-4936-db1b-9f9e1d8746ef"
   },
   "outputs": [],
   "source": [
    "#if you need a API Key from OpenAI\n",
    "#https://platform.openai.com/account/api-keys\n",
    "import openai\n",
    "import random\n",
    "import gradio as gr\n",
    "\n",
    "from getpass import getpass\n",
    "openai.api_key=getpass(\"OpenAI API Key: \")\n",
    "#model = \"gpt-3.5-turbo\"\n",
    "model = \"gpt-4o-mini\""
   ]
  },
  {
   "cell_type": "markdown",
   "id": "cf7bba1f-f84c-4066-9509-b98d3eaa6757",
   "metadata": {
    "id": "cf7bba1f-f84c-4066-9509-b98d3eaa6757"
   },
   "source": [
    "At OpenAI, we find three distinct roles:\n",
    "\n",
    "* system: Provides instructions to the model on how it should behave. We can define its personality here.\n",
    "* user: This role is used to send messages from the user.\n",
    "* assistant: The responses generated by the model.\n",
    "\n",
    "In the *context* variable, we will store the instructions for the model, which contain how it should act and the ice cream shop's menu."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "922f8d24",
   "metadata": {
    "id": "922f8d24"
   },
   "outputs": [],
   "source": [
    "#Creating the system part of the prompt\n",
    "#Read and understand it.\n",
    "\n",
    "context = [ {'role':'system', 'content':\"\"\"\n",
    "You work collecting orders in a delivery IceCream shop called\n",
    "I'm freezed.\n",
    "\n",
    "First welcome the customer, in a very friedly way, then collects the order.\n",
    "\n",
    "Your instuctions are:\n",
    "-Collect the entire order, only from options in our menu, toppings included.\n",
    "-Summarize it\n",
    "-check for a final time if everithing is ok or the customer wants to add anything else.\n",
    "-collect the payment, be sure to include topings and the size of the ice cream.\n",
    "-Make sure to clarify all options, extras and sizes to uniquely\n",
    "identify the item from the menu.\n",
    "-Your answer should be short in a very friendly style.\n",
    "\n",
    "Our Menu:\n",
    "The IceCream menu includes only the flavors:\n",
    "-Vainilla.\n",
    "-Chocolate.\n",
    "-Lemon.\n",
    "-Strawberry.\n",
    "-Coffe.\n",
    "\n",
    "The IceCreams are available in two sizes:\n",
    "-Big: 3$\n",
    "-Medium: 2$\n",
    "\n",
    "Toppings:\n",
    "-Caramel\n",
    "-White chocolate\n",
    "-melted peanut butter\n",
    "Each topping cost 0.5$\n",
    "\n",
    "\"\"\"} ]"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "7e0fd845-c725-4bb0-bac4-9ded5e1b75a9",
   "metadata": {
    "id": "7e0fd845-c725-4bb0-bac4-9ded5e1b75a9"
   },
   "source": [
    "This function is just a wrapper for the OpenAI API. It will receives the messages in OpenAI format and return the model response.\n",
    "\n",
    "Sample of OpenAI Conversation:\n",
    "\n",
    "[{\"role\":\"user\", \"content\":\"hi\"},\n",
    " {\"role\":\"system\", \"content\":\"what can I do for you.\"}]"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "b92b6dbe-f285-4955-b59f-84df43886a64",
   "metadata": {
    "id": "b92b6dbe-f285-4955-b59f-84df43886a64"
   },
   "outputs": [],
   "source": [
    "#This function will receive the different messages in the conversation,\n",
    "#and call OpenAI passing the full conversartion.\n",
    "def continue_conversation(messages, temperature=0):\n",
    "    response = openai.chat.completions.create(\n",
    "        model=model,\n",
    "        messages=messages,\n",
    "        temperature=temperature,\n",
    "    )\n",
    "    return response.choices[0].message.content\n"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "36235d9c-e1c0-4c64-8e70-8700d381dc20",
   "metadata": {
    "id": "36235d9c-e1c0-4c64-8e70-8700d381dc20"
   },
   "source": [
    "The GradioChat function will be called by Gradio and is responsible for maintaining the conversation. In the first parameter, it will receive the current message from the user, and in the second parameter, the complete history with all previous messages and responses.\n",
    "\n",
    "In this case, Gradio is responsible for maintaining the conversation history. This function is responsible for formatting it to work correctly with OpenAI models."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "2749aa82-d857-420f-8bda-21df6a531a38",
   "metadata": {
    "id": "2749aa82-d857-420f-8bda-21df6a531a38"
   },
   "outputs": [],
   "source": [
    "#The function that Gradio will use.\n",
    "def gradio_chat(message, history):\n",
    "    #Add the instructions to the prompt.\n",
    "    history_chat = context\n",
    "\n",
    "    #Add the history that Gradio send to us.\n",
    "    for user, assistant in history:\n",
    "        history_chat.append({\"role\":\"user\", \"content\":user})\n",
    "        history_chat.append({\"role\":\"assistant\", \"content\":assistant})\n",
    "\n",
    "    #Add the las user message.\n",
    "    history_chat.append({\"role\":\"user\", \"content\":message})\n",
    "\n",
    "    #Call OpenAI and return the response.\n",
    "    return continue_conversation(history_chat, 0)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "ec097501-b389-4f39-a66d-36e091d76700",
   "metadata": {
    "id": "ec097501-b389-4f39-a66d-36e091d76700"
   },
   "outputs": [],
   "source": [
    "#Customized gradio textbox.\n",
    "InputText = gr.Textbox(label=\"order\", info=\"Your Order here.\", scale= 6)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ab2993fd-fd13-4182-b646-42a551c74ccf",
   "metadata": {
    "id": "ab2993fd-fd13-4182-b646-42a551c74ccf"
   },
   "source": [
    "I'm going to use the simplest Gradio function for creating chats: *ChatInterface*. The first parameter it should receive is the previously built function responsible for maintaining the dialogue with OpenAI. In this case, *gradio_chat*.\n",
    "\n",
    "The function can be parameterized with a multitude of parameters, you can consult them in the official Gradio documentation: https://www.gradio.app/docs/gradio/chatinterface\n",
    "\n",
    "In this case, I pass it a customized textbox, otherwise we would have the default one, which would work the same, but without the customized text. I indicate that it should not show the retry or undo buttons, in addition to giving it a title and changing the text of the Submit button.\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "87bfc859-cb60-4e13-ac80-f03657422a5d",
   "metadata": {
    "colab": {
     "base_uri": "https://localhost:8080/",
     "height": 645
    },
    "id": "87bfc859-cb60-4e13-ac80-f03657422a5d",
    "outputId": "6f870176-855a-43fd-a2f3-f5714faf9496"
   },
   "outputs": [],
   "source": [
    "gr.ChatInterface(gradio_chat,\n",
    "                 textbox=InputText,\n",
    "                 retry_btn=None,\n",
    "                 undo_btn=None,\n",
    "                 title=\"I'm freezed\",\n",
    "                submit_btn=\"Order\").launch()"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "002dd2eb-f8c0-4908-b1ef-9d09aba74a6e",
   "metadata": {
    "id": "002dd2eb-f8c0-4908-b1ef-9d09aba74a6e"
   },
   "source": [
    "Gradio is very simple to use, yet incredibly powerful in terms of customization. It's a great tool for creating demos and quickly seeing how the built solutions work."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "68f02004-6047-43e8-a1d9-71660b795dce",
   "metadata": {
    "id": "68f02004-6047-43e8-a1d9-71660b795dce"
   },
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "colab": {
   "include_colab_link": true,
   "provenance": []
  },
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.12.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
